﻿#pragma once
/*********************************************************************************************************
 * 作者：魏星 2024-3-13
 * 思路来源：https://blog.csdn.net/baidu_30570701/article/details/127577959
 * 功能说明： 本文件实现json与结构体之间的转换功能
 * 使用说明：1. 定义json转换的专用结构体，使用本文件中的宏定义创建出专用结构体，示例如下：
 * structJ (Name,		// Name: 结构体名字
 *		mapping(type, var1);	// type：变量类型，可以使用基础类型(int, double, float, QString···)或者QList\QStringList
 *		mappingt(type, var2, key); // var: 变量名， key: json字符串对应的key。 
 *		prop(&var1, &var2)	// 变量指针
 * ) // mappping 和 mappingt的差别： mapping的变量对应json key值和变量名是相同的。mappingt 可以自定义json key值
 *			2. 使用方法： 和结构体的用法基本一致。 区别如下：
 * Name a = {};	// 创建结构体，不能通过 Name a = {1,2,3} 的方式实现对每个变量的赋值
 * QjsonObject json = a.toJson(); // 将结构体转换为 json
 * a.formJson(json);		// 将json转换为结构体
 * std::cout << a.var();	// 使用变量值。
**********************************************************************************************************/
#include <QJsonObject>
#include <QList>
#include <QVector>
#include <qjsonarray.h>
#include <QJsonDocument>



struct JsonInteface;
struct JsonReadInterface {
	// 读取key
	virtual const QString& key() const = 0;
	virtual QJsonValue value() = 0;
	// 写入值
	virtual void save(const QJsonValue& value) = 0;
	virtual ~JsonReadInterface() = default;
};

struct JsonInteface {
	JsonInteface() {}
	JsonInteface(const QByteArray& data)
	{
		fromJson(data);
	}
	JsonInteface(const QJsonObject& data)
	{
		fromJson(data);
	}

	virtual void fromJson(const QJsonObject& json) {
		for (const auto& iter : prop()) {
			if (json.contains(iter->key())) {
				iter->save(json.value(iter->key()));
			}
		}
	}

	virtual void fromJson(const QByteArray& byte) {
		QJsonDocument doc = QJsonDocument::fromJson(byte);
		fromJson(doc.object());
	}
	virtual QJsonObject toJson() {
		QJsonObject json;
		for (const auto& iter : prop()) {
			json.insert(iter->key(), iter->value());
		}
		return json;
	}

	virtual QByteArray toByteArray(QJsonDocument::JsonFormat type = QJsonDocument::Compact)
	{
		QJsonObject json = toJson();
		QJsonDocument doc(json);
		return doc.toJson(type);
	}

	virtual QList<JsonReadInterface*> prop() = 0;
	virtual ~JsonInteface() = default;
	
};

template<typename I> struct IteratorType;
template <typename T>
struct IteratorType<QList<T>> {
	using type = T;
};
template <typename T>
struct IteratorType<QVector<T>> {
	using type = T;
};

template <typename T>
struct JsonIdentify {
	using type = T;
};

template<typename T>
struct ConfigKey : JsonReadInterface {

	QString jKey;
	T jValue;
	explicit ConfigKey(QString key) :
		jKey(std::move(key)), jValue(T()) {}

	//赋值
	ConfigKey& operator=(const T& v) {
		jValue = v;
		return *this;
	}

	//引用取值
	T& operator()() {
		return jValue;
	}

	//const取值
	const T& operator()() const {
		return jValue;
	}

	template<typename K>
	using ValueType = typename std::conditional<std::is_base_of<JsonInteface, K>::value, JsonInteface, K>::type;

	const QString& key() const override
	{
		return jKey;
	}

	/*获取json数据*/
	QJsonValue value() override
	{
		return toJsonValue(jValue, JsonIdentify<ValueType<T>>());
	}
	template<typename I, typename K>
	static QJsonValue toJsonValue(I& val, JsonIdentify<K>)
	{
		return val;
	}
	template<typename I>
	static QJsonValue toJsonValue(I& val, JsonIdentify<JsonInteface>)
	{
		return dynamic_cast<JsonInteface*>(&val)->toJson();
	}
	template<typename I, typename K>
	static QJsonValue toJsonValue(I& val, JsonIdentify<QList<K>>)
	{
		QJsonArray json;
		for (auto& v : val)
		{
			json.append(toJsonValue(v, JsonIdentify<ValueType<K>>()));
		}
		return json;
	}
	template<typename I, typename K>
	static QJsonValue toJsonValue(I& val, JsonIdentify<QVector<K>>)
	{
		QJsonArray json;
		for (auto& v : val) {
			json.append(toJsonValue(v, JsonIdentify<ValueType<K>>()));
		}
		return json;
	}

	//QStringList类型
	template<typename I>
	static QJsonValue toJsonValue(I& value, JsonIdentify<QStringList>) {
		return QJsonArray::fromStringList(value);
	}

	void save(const QJsonValue& value) override
	{
		fromJsonValue(jValue, value, JsonIdentify<ValueType<T>>());
	}

	// 普通类型
	template<typename I, typename K>
	static void fromJsonValue(I& tagValue, const QJsonValue& value, JsonIdentify<K>)
	{	
		tagValue = value.toVariant().value<K>();
	}

	// Configkey类型
	template<typename I>
	static void fromJsonValue(I& tagValue, const QJsonValue& value, JsonIdentify<JsonInteface>)
	{
		dynamic_cast<JsonInteface*>(&tagValue)->fromJson(value.toObject());
	}

	template<typename I, typename K>
	static void fromJsonValue(I& tagValue, const QJsonValue& value, JsonIdentify<QList<K>>)
	{
		tagValue = QList<K>();
		auto vals = value.toArray();
		for (const auto& iter : vals) {
			typename IteratorType<QList<K>>::type temp;
			fromJsonValue(temp, iter, JsonIdentify<ValueType<K>>());
			tagValue.append(temp);
		}
	}

	template<typename I, typename K>
	static void fromJsonValue(I& tagValue, const QJsonValue& value, JsonIdentify<QVector<K>>)
	{
		tagValue = QVector<K>();
		auto vals = value.toArray();
		for (const auto& iter : vals) {
			typename IteratorType<QVector<K>>::type temp;
			fromJsonValue(temp, iter, JsonIdentify<ValueType<K>>());
			tagValue.append(temp);
		}
	}
};


#define mapping(type, var) ConfigKey<type> var{ #var }
#define mappingt(type, var, key) ConfigKey<type> var{key}
#define prop(...)	\
	QList<JsonReadInterface*> prop() override \
	{	\
		 return { __VA_ARGS__ };	\
	}

#define structJ(name, ...) \
	struct name : JsonInteface { \
		name(){} \
		name(const QByteArray& data) : JsonInteface(data) { };   \
		name(const QJsonObject& data) : JsonInteface(data) { } \
		__VA_ARGS__ \
	};

#define json_struct(name, ...) \
	struct name : JsonInteface { \
		name(){} \
		name(const QByteArray& data) : JsonInteface(data) { };   \
		name(const QJsonObject& data) : JsonInteface(data) { } \
		__VA_ARGS__ \
	};

